let express = require('express');
let mysql = require('mysql');
let redis = require('redis');
let crypto = require('crypto');
let nodecache = require('node-cache');

function globalpool(config) {
    let key = crypto.createHash('md5').update(JSON.stringify(config)).digest('hex');
    if (!global.mysqlddd2) global.mysqlddd2 = {};
    if (!global.mysqlddd2[key]) {
        global.mysqlddd2[key] = mysql.createPool(config);
    }
    return global.mysqlddd2[key];
}

function globalredis(config_redis) {
    let key = crypto.createHash('md5').update(JSON.stringify(config_redis)).digest('hex');
    if (!global.redis) { global.redis = {}; };
    if (!global.redis[key]) {
        global.redis[key] = redis.createClient(config_redis);
    }
    return global.redis[key];
}

function globalnodecache(config_redis) {
    let key = crypto.createHash('md5').update(JSON.stringify(config_redis)).digest('hex');
    if (!global.nodecache) { global.nodecache = {}; };
    if (!global.nodecache[key]) {
        global.nodecache[key] = new nodecache({
            stdTTL: 30, //标准ttl=30秒。
            checkperiod: 120, //每120秒删除一次过期键值。
        })
    }
    return global.nodecache[key];
}

async function tokenresolve(config_redis, token) {
    if (config_redis && token) {

        let jtoken = globalnodecache(config_redis).get("token:" + token);
        if (jtoken) return jtoken;

        let client = globalredis(config_redis);
        jtoken = await new Promise((resolve, reject) => {
            client.get('token:' + token, function(err, jtoken) {
                if (err) {
                    reject(err);
                } else {
                    globalnodecache(config_redis).set("token:" + token, jtoken);
                    resolve(jtoken);
                }
            })
        });
        return jtoken;
    } else {
        return ('{}');
    }
}

function execPromise(config_mysql, sp, data, config_redis, token) {
    return new Promise(async(resolve, reject) => {

        let jtoken = await tokenresolve(config_redis, token);

        // console.log({ token, jtoken });
        // config.multipleStatements = true;
        let pool = globalpool(config_mysql);
        let cmd = 'select ?,? into @token,@jdata;call ??(@token,@jdata);select @jdata as jdata;';

        pool.query(cmd, [jtoken, JSON.stringify(data), sp],
            function(err, result, fields) {
                if (!err) {
                    let last = result.length - 1;
                    if (result[last][0].jdata !== undefined) {
                        var r = JSON.parse(result[last][0].jdata);
                        resolve(r);
                    } else {
                        reject({
                            err_code: 6,
                            err_message: "no result"
                        });
                    }
                } else {
                    reject({
                        err_code: err.errno,
                        dddState: err.sqlState,
                        err_message: err.sqlMessage,
                        sql_err: err
                    });
                }
            });
    })
}

function router(config_mysql, config_redis, logincookie) {
    let api = express.Router();

    api.get('/', (req, res) => {
        res.json({ provider: 'mysqlddd' });
    });

    api.get('/:sp', function(req, res, next) {
        console.log({ logincookie, token: req.cookies[logincookie] });
        execPromise(
            config_mysql,
            "ddd_" + req.params.sp,
            req.query,
            config_redis,
            logincookie ? req.cookies[logincookie] : undefined
        ).then(data => {
            res.json(data);
        }).catch(err => {
            res.status(500);
            res.json(err);
        })
    })

    api.post('/:sp', (req, res, next) => {
        execPromise(
            config_mysql,
            "ddd_" + req.params.sp,
            req.body,
            config_redis,
            logincookie ? req.cookies[logincookie] : undefined
        ).then(data => {
            res.json(data);
        }).catch(err => {
            res.status(500);
            res.json(err);
        })
    })
    return api;
}

module.exports = {
    execPromise: execPromise,
    router: router
}
